#include "tcp_client.h"

client_info client;  // 客户端数据
int flag = 1;  // 用于控制两个线程是否结束
int read_flag = 0;  // 用于控制读线程是否睡眠,1睡眠
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  // 线程互斥锁
pthread_cond_t  cond  = PTHREAD_COND_INITIALIZER;   // 线程条件变量
int single_chat_fd;                                // 用于单聊获取数据的socket

int main(void) {
    printf("请输入客户端名称:\n");
    scanf("%s", client.name);
    char img_pos[4];
    printf("请输入客户端头像(1-10):\n");
    scanf("%s",img_pos);
    strcpy(client.send_head_portrait_name,img_name_arr[atoi(img_pos)-1]);
	
    init_socket();

    pthread_t th1, th2;

    // 创建客户端接收数据线程
    if (pthread_create(&th1, NULL, client_recv_action, NULL) != 0) {
        perror("pthread_create");
    }

    // 创建客户端发送数据线程
    if (pthread_create(&th2, NULL, client_send_action, NULL) != 0) {
        perror("pthread_create");
    }

    pthread_join(th1, NULL);
    pthread_join(th2, NULL);

    close(client.client_fd);//关闭客户端连接

    return 0;
}

// socket初始化
int init_socket() {
    struct sockaddr_in server_addr;  // 服务器结构体

    // 申请网络套接字文件
    if ((client.client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        return 1;
    }
    printf("申请IPV4的TCP协议的网络套接字成功\n");

    bzero(&server_addr, sizeof(struct sockaddr_in));
    //初始化服务器端的套接字，并用htons和htonl将端口和地址转成网络字节序
    server_addr.sin_family = AF_INET;  // 指定协议是使用IPV4的协议
    server_addr.sin_port = htons(SERVER_PORT);  // 指定端口号,htons用短整型的方式转化为网络字节序
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);//将字符串的IP地址转化为网络字节序的数据

    // 连接服务器
    if (connect(client.client_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == -1) {
        perror("connect");
        return -1;
    }
    printf("[%s]连接服务器成功\n", client.name);

    // 发送登录信息
    client_login();
}

// 客户端接收数据
void *client_recv_action(void *args) {
    message recv_msg;     // 接收的数据
    int data_size;        // 数据的大小
    while (flag) {
        // 随眠当前线程,等待另一条线程获取数据
        if (read_flag == 1) {
            pthread_mutex_lock(&mutex);
            printf("读线程已睡眠\n");
            pthread_cond_wait(&cond, &mutex);
        }
        memset(&recv_msg, 0, sizeof(message));
        data_size = recv(client.client_fd, &recv_msg, sizeof(message), 0);  // 从服务器读取数据
        if (data_size < 0) {
            break;
        }
        switch (recv_msg.msg_type) {
            case LOGIN: {
                printf("%s:%s\n", recv_msg.name, recv_msg.text);
                break;
            }
            // case AMOUNT: {
            //     client_amount = atoi(recv_msg.text);
            //     printf("client_amount=%d\n", client_amount);
            //     // 唤醒写线程
            //     pthread_cond_signal(&cond);
            //     pthread_mutex_unlock(&mutex);
            //     break;
            // }
            // case CLIENTS: {
            //     printf("%s:%s\n", recv_msg.name, recv_msg.text);
            //     break;
            // }
            case SINGLE: {
                printf("%s:%s\n", recv_msg.name, recv_msg.text);
                break;
            }
            case GROUP: {
                printf("%s:%s\n", recv_msg.name, recv_msg.text);
                break;
            }
            case QUIT: {
                printf("%s:%s\n", recv_msg.name, recv_msg.text);
                break;
            }
            default:
                break;
        }
    }
}
// 客户端发送数据
void *client_send_action(void *args) {
    int op; // 选项
    char ch;
    while (flag) {
        while ((ch = getchar()) != '\n' && ch != EOF); // 清空缓冲区
        printf("请选择:(1)单聊 (2)群聊 (3)下线\n");
        scanf("%d", &op);
        switch (op) {
            case 1: {
                // client_single_chat();
				client_single_setout();
                break;
            }
            case 2: {
                client_group_chat();
                break;
            }
            case 3: {
                client_quit();
                flag = 0;
                break;
            }
            default:
                break;
        }
    }
}

// 客户端登录
void client_login() {
    message send_msg;          // 发送的数据
    memset(&send_msg, 0, sizeof(message));

    strcpy(send_msg.name, client.name);
    send_msg.msg_type = LOGIN;
    // strcpy(send_msg.text, "上线了");

    send(client.client_fd, &send_msg, sizeof(message), 0); // 客户端发送数据
}

// 客户端单聊准备
void client_single_setout()
{
    pthread_mutex_lock(&mutex);
    single_chat_socket();
    // 先从服务器获取除自己以外的客户端信息
    message send_msg; // 发送的数据
    memset(&send_msg, 0, sizeof(message));

    // 告诉服务端当前客户端需要其他客户端的信息
    strcpy(send_msg.name, client.name);
    send_msg.msg_type = CLIENTS;
    printf("single_chat_fd=%d,send_msg.msg_type=%c,name=%s\n", single_chat_fd, send_msg.msg_type, send_msg.name);
    send(single_chat_fd, &send_msg, sizeof(message), 0); // 客户端发送数据

    int client_amount = 0; // 客户端数量
    // 1、先获取个数，以便接收时确定数组长度
    memset(&send_msg, 0, sizeof(message));

    if (recv(single_chat_fd, &send_msg, sizeof(message), 0) > 0)
    {
        // 从服务器读取数据
        client_amount = atoi(send_msg.text);
        printf("client_amount=%d\n", client_amount);
		if (client_amount == 1){
			printf("没有其他用户登录\n");
			goto this_flag;
		}
        if (client_amount <= 0)
        {
            printf("获取数据出错\n");
            goto this_flag;
        }
        // 2、获取所有客户端信息
        client_data clients[client_amount];
        memset(clients, 0, sizeof(clients));
        if (recv(single_chat_fd, clients, sizeof(clients), 0) > 0) {
            printf("请选择想要联系的用户:\n");
            for (int i = 0; i < client_amount; i++) {
                if (strcmp(client.name, clients[i].name) != 0) { // 不打印自己
                    printf("[%d] %s\n", i + 1, clients[i].name);
                }
            }
            int index;  // 选择的下标
            scanf("%d", &index);
            if (index > 0 && index < client_amount + 1) {  // 判断输入的数是否正确
                message send_msg;          // 发送的数据
                memset(&send_msg, 0, sizeof(message));
                strcpy(send_msg.name, client.name);
				strcpy(send_msg.send_head_portrait_name,client.send_head_portrait_name);
                send_msg.msg_type = SINGLE;
                send_msg.target_fd = clients[index - 1].fd;
				send_msg.source_fd = client.client_fd;
                printf("请输入你想要发送的内容:\n");
                scanf("%s", send_msg.text);
                send(client.client_fd, &send_msg, sizeof(message), 0); // 客户端发送数据
            }
        }
    }

this_flag:
    // 告诉服务器退出
    memset(&send_msg, 0, sizeof(message));
    send_msg.msg_type = EXIT;
    send(single_chat_fd, &send_msg, sizeof(message), 0); // 客户端发送数据
    close(single_chat_fd);

    pthread_mutex_unlock(&mutex);
}

// 客户端单聊线程
int single_chat_socket()
{
    struct sockaddr_in server_addr; // 服务器结构体

    // 申请网络套接字文件
    if ((single_chat_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket");
        return 1;
    }
    printf("申请single_chat_fd网络套接字成功\n");

    bzero(&server_addr, sizeof(struct sockaddr_in));
    //初始化服务器端的套接字，并用htons和htonl将端口和地址转成网络字节序
    server_addr.sin_family = AF_INET;                   // 指定协议是使用IPV4的协议
    server_addr.sin_port = htons(SERVER_PORT);          // 指定端口号,htons用短整型的方式转化为网络字节序
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); //将字符串的IP地址转化为网络字节序的数据

    // 连接服务器
    if (connect(single_chat_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == -1)
    {
        perror("connect");
        return -1;
    }
    printf("single_chat连接服务器成功\n");
	return 0;
}

// 客户端单聊
void client_single_chat() {
    read_flag = 1; // 睡眠读线程,防止其读取当前线程需要的数据

    // 先从服务器获取除自己以外的客户端信息
    message send_msg;          // 发送的数据
    memset(&send_msg, 0, sizeof(message));

    // 告诉服务端当前客户端需要其他客户端的信息
    strcpy(send_msg.name, client.name);
    send_msg.msg_type = CLIENTS;
    send(client.client_fd, &send_msg, sizeof(message), 0); // 客户端发送数据

    int client_amount = 0;  // 客户端数量
    // printf("client_amount:%d\n", client_amount);
    // 1、先获取个数，以便接收时确定数组长度

    // if (recv(client.client_fd, &client_amount, sizeof(client_amount), 0) > 0) {
    memset(&send_msg, 0, sizeof(message));
    if (recv(client.client_fd, &send_msg, sizeof(message), 0) > 0) { // 从服务器读取数据
        client_amount = atoi(send_msg.text);
        printf("client_amount=%d\n", client_amount);
        if (client_amount == 1) {
            printf("没有其它用户上线\n");
            goto this_flag;
        }
        if (client_amount == 0) {
            printf("获取数据出错\n");
            goto this_flag;
        }
        // 2、获取所有客户端信息
        client_data clients[client_amount];
        memset(clients, 0, sizeof(clients));
        if (recv(client.client_fd, clients, sizeof(clients), 0) > 0) {
            printf("请选择想要联系的用户:\n");
            for (int i = 0; i < client_amount; i++) {
                if (strcmp(client.name, clients[i].name) != 0) { // 不打印自己
                    printf("[%d] %s\n", i + 1, clients[i].name);
                }
            }
            int index;  // 选择的下标
            scanf("%d", &index);
            if (index > 0 && index < client_amount + 1) {  // 判断输入的数是否正确
                message send_msg;          // 发送的数据
                memset(&send_msg, 0, sizeof(message));

                strcpy(send_msg.name, client.name);
				strcpy(send_msg.send_head_portrait_name, client.send_head_portrait_name);
                send_msg.msg_type = SINGLE;
                send_msg.target_fd = clients[index - 1].fd;
                printf("请输入你想要发送的内容:\n");
                scanf("%s", send_msg.text);
                send(client.client_fd, &send_msg, sizeof(message), 0); // 客户端发送数据
            }
        }
    }

this_flag:
    // 唤醒读线程
    read_flag = 0;
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);

    return ;
}

// 客户端群聊
void client_group_chat() {
    message send_msg;          // 发送的数据
    memset(&send_msg, 0, sizeof(message));
	strcpy(send_msg.send_head_portrait_name, client.send_head_portrait_name);
    strcpy(send_msg.name, client.name);
    send_msg.msg_type = GROUP;
    printf("请输入内容\n");
    scanf("%s", send_msg.text);
    printf("Input:%s\n", send_msg.text);

    send(client.client_fd, &send_msg, sizeof(message), 0); // 客户端发送数据
}

// 客户端退出
void client_quit() {
    message send_msg;          // 发送的数据
    memset(&send_msg, 0, sizeof(message));

    strcpy(send_msg.name, client.name);
    send_msg.msg_type = QUIT;
    // strcpy(send_msg.text, "下线了");

    send(client.client_fd, &send_msg, sizeof(message), 0); // 客户端发送数据
}